home *** CD-ROM | disk | FTP | other *** search
- #include "util.h"
- #include "nexec.h"
- #include <signal.h>
- #ifndef NOFCNTL
- #include <fcntl.h>
- #endif
-
- /* generic fork/exec procedure, passing re-positioned fd's */
-
- /* Jun 81 D. Crocker make regfdary loop tmp<=HIGHFD
- * May 82 D. Crocker make close of fd tmp<=HIGHFD
- * Jul 82 D. Crocker make vax version, to use vfork
- * Mar 84 D. Kingston Changed to use _NFILE from stdio.h instead
- * of HIGHFD. Steve Kille: you don't have
- * to shorten the array if you have less fds.
- */
-
- extern int numfds;
-
- LOCFUN tryfork();
-
- /* VARARGS4 */
- #if sparc
- #include <varargs.h>
- #define MAXARGS 20
- nexecl(va_alist)
- va_dcl
- {
- register int i;
- va_list ap;
- int proctyp, pgmflags;
- int *fdarray;
- char *pgm;
- char *pgmparm[MAXARGS];
-
- va_start(ap);
- proctyp = va_arg(ap, int);
- pgmflags = va_arg(ap, int);
- fdarray = va_arg(ap, int *);
- pgm = va_arg(ap, char *);
- for (i = 0; i < MAXARGS; ++i) {
- if ((pgmparm[i] = va_arg(ap, char *)) ==(char *)0)
- break;
- }
- va_end(ap);
- return(nexecv(proctyp, pgmflags, fdarray, pgm, pgmparm));
- }
- #else /* sparc */
- #ifdef NO_VARARGS
- nexecl(proctyp, pgmflags, fdarray, pgm, pgmparm, a,b,c,d,e,f,g,h,i,j,k,l,m)
- #else
- nexecl(proctyp, pgmflags, fdarray, pgm, pgmparm)
- #endif /* NO_VARARGS */
- int proctyp, /* exec / fork / fork-exec */
- pgmflags, /* parent wait? disable interrupts? */
- *fdarray; /* what current fd's go where? */
- char *pgm, /* what program to exec? */
- *pgmparm; /* its parameters vector */
- {
- return(nexecv(proctyp, pgmflags, fdarray, pgm, &pgmparm));
- }
- #endif /* sparc */
-
- nexecv(proctyp, pgmflags, fdarray, pgm, pgmparm)
- int proctyp,
- pgmflags,
- *fdarray;
- char *pgm,
- *pgmparm[];
- {
- register int fd;
- int status;
- int childid;
- sigtype (*(osig1))();
- sigtype (*(osig2))();
- sigtype (*(osig3))();
-
- if (proctyp != PUREXEC) {
- /* printf("This is a forking call.\n"); */
- childid = tryfork();
- if (childid == -1)
- return(NOTOK);
- /* printf("Successful fork\n"); */
- if (childid != 0) { /* parent process */
- if (pgmflags & FRKPIGO) { /* disable parent signals */
- /* printf("Parent to be non-interruptible\n"); */
- osig1 = signal(SIGHUP, SIG_IGN);
- osig2 = signal(SIGINT, SIG_IGN);
- osig3 = signal(SIGQUIT, SIG_IGN);
- }
- if (((proctyp == FRKEXEC) &&(pgmflags & FRKWAIT)) ||
- proctyp == SPNEXEC) {
- /* printf("Parent is to wait\n"); */
- status = pgmwait(childid);
- if (pgmflags & FRKPIGO) {
- (void)signal(SIGHUP, osig1);
- (void)signal(SIGINT, osig2);
- (void)signal(SIGQUIT, osig3);
- }
- return(status);
- }
- return(childid);
- }
- if (proctyp == SPNEXEC) { /* want it to be a spawn */
- /* printf("This is a spawn\n"); */
- switch(childid = tryfork()) {
- case 0:
- break; /* gets to do its thing */
-
- case NOTOK: /* oops */
- exit(NOTOK);
-
- default: /* grandchild: kill middle proc */
- exit(0);
- }
- }
- }
- if (fdarray) { /* re-align fd array list */
- /* first do the re-positions */
- for (fd = 0; fd < numfds; fd++) {
- if (fdarray[fd] != CLOSEFD && fdarray[fd] != fd) {
- #ifndef NODUP2
- (void)dup2(fdarray[fd], fd);
- #else /* NODUP2 */
- (void)close(fd);
- #ifndef NOFCNTL
- fcntl(fdarray[fd], F_DUPFD, fd);
- #else /* NOFCNTL */
- {
- int dupfd;
-
- while ((dupfd = dup(fdarray[fd])) < fd && dupfd != -1)
- ;
- /* did we get right fd? */
- }
- #endif /* NOFCNTL */
- #endif /* NODUP2 */
- }
- }
- for (fd = 0; fd < numfds; fd++)
- if (fdarray[fd] == CLOSEFD) {
- /* printf("Closing %2d\n", fd); */
- /* get rid of unwanted ones */
- (void)close(fd);
- }
- }
-
- if (pgmflags & FRKCIGO) {
- /* printf("Child's interrupts to be disabled\n"); */
- (void)signal(1, SIG_IGN);
- (void)signal(2, SIG_IGN);
- (void)signal(3, SIG_IGN);
- }
-
- /* printf("Execing %s\n", pgm); */
- execv(pgm, pgmparm);
- /* printf("Exec not successful\n"); */
- switch(proctyp) {
- case PUREXEC:
- return(NOTOK);
-
- default: /* caller can deal with it */
- if (pgmflags & FRKERRR)
- return(NOTOK);
- }
- exit(NOTOK);
- /* NOTREACHED */
- }
-
- pgmwait(childid)
- int childid; /* process id of child to collect */
- {
- int status;
- register int retval;
-
- while ((retval = wait(&status)) != childid)
- if (retval == NOTOK)
- return(NOTOK);
-
- return(gwaitval(status));
- }
-
-
- LOCFUN
- tryfork()
- {
- register int childid;
- register int tried;
-
- tried = NUMTRY;
- do {
- if ((childid = fork()) < 0)
- sleep(1);
- else
- return(childid);
- } while (tried--);
- return(childid);
- }
-